"-----------------------------------------------------------------------------
"- default options
"-----------------------------------------------------------------------------
let mapleader=' '
let g:mapleader=' '
set shortmess=atcCIF
set history=2000
set undofile
set autoread
set cursorline
set number
set relativenumber
set splitbelow
set splitright
set list
set listchars=tab:>·,trail:•,precedes:«,extends:»,nbsp:%
set autochdir
set wildmode=longest,full
set wildignore=*.o,*~,*.pyc,*.class
set showmatch
set matchtime=1
set ignorecase
set smartcase
set shada='270,f1,<1000,:270,s100,!
set pumheight=27
set complete=.,w,b,u,f
set completeopt=menu,menuone,longest,preview,popup,noselect,fuzzy
set completefuzzycollect=keyword,files,whole_line
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,latin1
set formatoptions+=mB
set spo+=camel
set spellfile=~/.config/nvim/spell/en.utf-8.add
set dictionary=~/.config/nvim/spell/engspchk.dict
set thesaurus=~/.config/nvim/thesaurus/english.txt
set statusline=%{utils_func#printMode()}\ %r%y%m\ %F%=[%L:%l,%2v]\ [%{utils_func#humanReadableSize(getfsize(expand(@%)))}]\ [%{&ff}]\ [%{(&fenc!=''?&fenc:&enc)}%{(&bomb?\\",BOM\\":\\"\\")}]\ CZ
set laststatus=3
set matchpairs+=<:>
set noshowmode
set sidescroll=50
set diffopt-=linematch:40
set diffopt+=linematch:60
if executable("rg")
  set grepprg=rg\ --vimgrep\ --smart-case\ -M\ 200\ --max-columns-preview\ --follow
endif

"-----------------------------------------------------------------------------
"- configuration write by lua
"-----------------------------------------------------------------------------
lua <<EOF
-- Change querying background color escape sequence via OSC 11 when neovim opened in tmux
-- See https://github.com/neovim/neovim/issues/17070#issuecomment-1086775760
-- if vim.env.TMUX then
--   vim.loop.fs_write(2, "\27Ptmux;\27\27]11;?\7\27\\", -1, nil)
-- end

-- From https://www.reddit.com/r/neovim/comments/zc720y/comment/iyvcdf0
vim.on_key(function(char)
  if vim.fn.mode() == "n" then
    local new_hlsearch = vim.tbl_contains({ "<CR>", "n", "N", "*", "#", "?", "/" }, vim.fn.keytrans(char))
    if vim.opt.hlsearch:get() ~= new_hlsearch then
      vim.opt.hlsearch = new_hlsearch
    end
  end
end, vim.api.nvim_create_namespace "auto_hlsearch")

-- From https://this-week-in-neovim.org/2023/Jan/30#tips
-- see :h :DiffOrig, this is a way with little improvements in Lua
vim.api.nvim_create_user_command('DiffOrig', function()
  -- Get start buffer
  local start = vim.api.nvim_get_current_buf()

  -- `vnew` - Create empty vertical split window
  -- `set buftype=nofile` - Buffer is not related to a file, will not be written
  -- `0d_` - Remove an extra empty start row
  -- `diffthis` - Set diff mode to a new vertical split
  vim.cmd('vnew | set buftype=nofile | read ++edit # | 0d_ | diffthis')

  -- Get scratch buffer
  local scratch = vim.api.nvim_get_current_buf()

  -- `wincmd p` - Go to the start window
  -- `diffthis` - Set diff mode to a start window
  vim.cmd('wincmd p | diffthis')

  -- Map `q` for both buffers to exit diff view and delete scratch buffer
  for _, buf in ipairs({ scratch, start }) do
    vim.keymap.set('n', 'q', function()
      vim.api.nvim_buf_delete(scratch, { force = true })
      vim.keymap.del('n', 'q', { buffer = start })
    end, { buffer = buf })
  end
end, {})
EOF

"-----------------------------------------------------------------------------
"- autocmds
"-----------------------------------------------------------------------------
" Move to exit position when open file, if this not work ,make sure .viminfo is writable for you
" see :h last-position-jump
augroup RestoreCursor
  autocmd!
  autocmd BufReadPost *
    \ let line = line("'\"")
    \ | if line >= 1 && line <= line("$") && &filetype !~# 'commit'
    \      && index(['xxd', 'gitrebase'], &filetype) == -1
    \      && !&diff
    \ |   execute "normal! g`\""
    \ | endif
augroup END

augroup SaveAndMkdir
  au!
  " Auto-create parent directories (except for URIs "://").
  " see :h ++p
  au BufWritePre,FileWritePre * if @% !~# '\(://\)' | call mkdir(expand('<afile>:p:h'), 'p') | endif
augroup end

augroup HighlightWhenYank
  au!
  " Highlighting a selection on yank, see :h vim.hl
  au TextYankPost * silent! lua vim.hl.on_yank {higroup="IncSearch", timeout=200}
augroup end

"-----------------------------------------------------------------------------
"- mapping
"-----------------------------------------------------------------------------
nnoremap <space> <Nop>
noremap H ^
noremap L $
nnoremap k gk
nnoremap gk k
nnoremap j gj
nnoremap gj j
nnoremap <leader>j <C-W>j
nnoremap <leader>k <C-W>k
nnoremap <leader>h <C-W>h
nnoremap <leader>l <C-W>l
nnoremap <silent> <leader>d :bd<CR>
nnoremap <leader>e :e<Space>
nnoremap <leader>q :q<CR>
nnoremap <leader>Q :qa<CR>
nnoremap <leader>1 :q!<CR>
nnoremap <leader>2 :wq<CR>
nnoremap <leader>w :w<CR>
nnoremap <leader>x :x<CR>
nnoremap <leader>as ggVG
nnoremap U <C-r>
nnoremap <leader><leader> <c-^>
nnoremap <silent> <leader>o :<C-u>call append(line("."),   repeat([""], v:count1))<CR>
nnoremap <silent> <leader>O :<C-u>call append(line(".")-1, repeat([""], v:count1))<CR>
vnoremap <leader>ys "+y
nnoremap <leader>yy "+yy
nnoremap <leader>yp "+p
inoremap <C-x>r <Cmd>reg <bar> call feedkeys("\<C-r>" . input('> '), 'i')<CR>
nnoremap gp `[v`]
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
nnoremap <silent> <C-j> :bNext<CR>
nnoremap <silent> <C-k> :bprevious<CR>
noremap <silent> <Leader>ll :call matchadd('PmenuSel', '\%'.line('.').'l')<CR>
nnoremap <silent> <Leader>lc :call clearmatches()<CR>
set cedit=\<C-L>
cnoremap <C-a> <Home>
cnoremap <C-f> <Right>
cnoremap <C-b> <Left>
cnoremap <C-d> <Del>
cnoremap <C-k> <C-\>e(strpart(getcmdline(), 0, getcmdpos() - 1))<CR>
"cnoremap <M-b> <S-Left>
"cnoremap <M-f> <S-Right>
"cnoremap <M-d> <S-Right><C-W>
function! s:optCmd(opt) abort
  "see https://github.com/vim/vim/issues/12623"
  "let l:pat = '\k*\%' . l:cursorPos . 'c\zs\%(\k\+\|\%(\k\@!.\)\+\)'
  let l:cursorPos = getcmdpos()
  let l:pat = '\k*\%' . l:cursorPos . 'c\zs\%(\k\+\|.\{-}\<\k\+\>\|\%(\k\@!.\)\+\)'
  let l:cmdlineInput = getcmdline()
  let l:cmdlineLen = strlen(l:cmdlineInput)
  if a:opt=="del"
    if l:cursorPos == l:cmdlineLen + 1
      return ''
    endif
    return repeat("\<Del>", strchars(matchstr(l:cmdlineInput, l:pat)))
  elseif a:opt=="forward"
    if l:cursorPos == l:cmdlineLen + 1
      return ''
    endif
    return repeat("\<Right>", strchars(matchstr(l:cmdlineInput, l:pat)))
  elseif a:opt=="back"
    if l:cursorPos == 1
      return ''
    endif
    let l:reversed_cmdlineInput = join(reverse(split(l:cmdlineInput, '\zs')), '')
    let l:pos = (l:cursorPos < l:cmdlineLen + 1)
          \ ? l:cmdlineLen - l:cursorPos + 2
          \ : 1
    let l:pat = '\k*\%' . l:pos . 'c\zs\%(\k\+\|.\{-}\<\k\+\>\|\%(\k\@!.\)\+\)'
    return repeat("\<Left>", strchars(matchstr(l:reversed_cmdlineInput, l:pat)))
  endif
endfunction
cnoremap <expr> <M-b> <SID>optCmd("back")
cnoremap <expr> <M-f> <SID>optCmd("forward")
cnoremap <expr> <M-d> <SID>optCmd("del")
inoremap <silent><expr> <TAB>
      \ pumvisible() ? "\<C-n>" :
      \ utils_func#checkBackSpace() ? "\<TAB>" : "\<C-n>"
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
" Maximize buffer at a single tabpage
function! ToggleTabEdit() abort
  if winnr() == 1 && tabpagenr() != 1
    let l:save_pos = getpos('.')
    let l:buf_name = buffer_name()
    exec "normal \<C-W>c"
    if l:buf_name == buffer_name()
      call setpos('.', l:save_pos)
    endif
  else
    exec "tab sp|normal zz"
  endif
endfunction
nnoremap <silent><leader>m :call ToggleTabEdit()<CR>

if &diff
  nnoremap <C-n> ]c
  nnoremap <C-p> [c
  nnoremap <leader>1 :qa<CR>
endif

"-----------------------------------------------------------------------------
"- plugins
"-----------------------------------------------------------------------------
" Load dein
if &runtimepath !~# '/dein.vim'
  let s:dein_dir = expand('~/.cache/dein_nvim/repos/github.com/Shougo/dein.vim')
  if !isdirectory(s:dein_dir)
    execute '!git clone https://github.com/Shougo/dein.vim' s:dein_dir
  endif
  execute 'set runtimepath^=' . substitute(fnamemodify(s:dein_dir, ':p') , '[/\\]$', '', '')
endif

let g:dein#auto_recache = v:true
let g:dein#enable_notification = v:true
let g:dein#install_log_filename = expand('~/dein.log')

let s:dein_nvim_path = expand('~/.cache/dein_nvim')
if dein#min#load_state(s:dein_nvim_path)
  let s:nvim_base_dir = fnamemodify(expand('<sfile>'), ':h') . '/'
  let s:dein_toml = s:nvim_base_dir . 'dein.toml'
  let s:dein_ft_toml = s:nvim_base_dir . 'deinft.toml'
  call dein#begin(s:dein_nvim_path, [expand('<sfile>'), s:dein_toml, s:dein_ft_toml])
  call dein#load_toml(s:dein_toml)
  call dein#load_toml(s:dein_ft_toml)
  call dein#end()
  call dein#save_state()

endif
if has('vim_starting')
  call dein#call_hook('source')
  call dein#call_hook('post_source')
endif

filetype plugin indent on

lua require'nvim-messages'
